package com.yantong.controller.notify;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.yantong.config.LocalRedis;
import com.yantong.constant.ProductType;
import com.yantong.exception.BDException;
import com.yantong.mapper.OrderMapper;
import com.yantong.mapper.OrderSplitInfoMapper;
import com.yantong.pay.yfz.domain.pay.domain.refund.RefundApplyResponse;
import com.yantong.pay.yfz.domain.pay.domain.split.SplitResultQueryResponse;
import com.yantong.pay.yfz.domain.pay.domain.wechatJSAPI.WxJsOrderNotify;
import com.yantong.pay.yfz.util.Config;
import com.yantong.pay.yfz.util.RsaUtils;
import com.yantong.pojo.*;
import com.yantong.service.*;
import com.yantong.utils.ValidateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.List;

/**
 * 提供给第三方的回调接口
 * @author: juzi
 * @date: 2021/10/27
 * @time: 14:58
 */
@Controller
@RequestMapping("/notify")
public class NotifyController{

    public static final int WXPAY_ORDER = 0; //订单支付
    public static final int WXPAY_VIP = 1;   //购买vip
    public static final int WXPAY_SHIPCARD = 2;   //购买充值卡
    public static final int WXPAY_LOCALLIFE_VIP = 3;   //本地生活会员
    public static final int WXPAY_LOCALLIFE_PREFERENTIAL_CARD = 4; //本地生活商户优惠卡
    private static final double VIP_PRICE = 199;

    private static final Logger logger = LoggerFactory.getLogger(NotifyController.class);

    @Autowired
    private OrderService orderService;
    @Autowired
    private CentreService centreService;
    @Autowired
    private ProductAuthorityService ProductAuthorityService;
    @Autowired
    private PayService payService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private LocalRedis localRedis;
    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private OrderSplitInfoMapper orderSplitInfoMapper;


    /**
     * 易分账支付回调(易票联支付回调)
     */
    @RequestMapping("/yfz/order/notify")
    public void yfzOrderNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        JSONObject attach = null;
        int payType = 0;
        String sign = request.getHeader("x-efps-sign");
        BufferedReader br = request.getReader();
        String str = "", wholeStr = "";
        System.out.println("---------------------------------------------------");
        while ((str = br.readLine()) != null) {
            wholeStr += str;
        }
        logger.info("body:" + wholeStr);
        logger.info("sign:" + sign);
        System.out.println("---------------------------------------------------");

        PrintWriter writer = response.getWriter();
        JSONObject jsonObject = new JSONObject();
        if (wholeStr != null && !wholeStr.equals("") && sign != null && !sign.equals("")) {
            WxJsOrderNotify obj = JSONObject.parseObject(wholeStr, WxJsOrderNotify.class);
            int count = -1;
            Order order = orderService.getOrderByTradNo(obj.getOutTradeNo());
            if (order == null) {
                logger.error("订单未查到OutTradeNo" + obj.getOutTradeNo());
                jsonObject.put("returnCode", "-1");
                jsonObject.put("returnMsg", "inLegal data");
                writer.print(jsonObject.toJSONString());
                writer.close();
            } else {
                Centre centre = centreService.getCentreById(order.getCentreId());
                boolean result = RsaUtils.vertify(RsaUtils.getPublicKey(Config.getPublicKeyFile(centre.getYplPublicKey())), wholeStr, sign);
                System.out.println("验签结果:" + result);
                if (result) {
                    //查看订单是否在缓冲区
                    Object orderCash = localRedis.get("yfzOrderNotify".concat(obj.getOutTradeNo()));
                    //不在缓冲区进入逻辑
                    if (orderCash == null || orderCash.toString().trim().equals("false")) {
                        //存入缓存 去幂等性
                        localRedis.setByHours("yfzOrderNotify".concat(obj.getOutTradeNo()), true, 2);

                        attach = JSON.parseObject(order.getPayattach());
                        payType = attach.getIntValue("type");

                        logger.info("订单状态ok==================================" + payType);
                        try {
                            //如果为大礼包订单
                            if (order.getOrderType() == ProductType.FreeCharge.getType()) {
                                ProductAuthorityService.MemberProductAuthoityUpdate(order);
                            }
                            if (payType == WXPAY_ORDER) {
                                Long orderId = attach.getLong("orderId");
                                //生成门店费率记录
                                //collectionFlowService.orderByCollectionFlowInsert(order);
                                logger.info("逻辑wx修改==================================");
                                count = payService.wxPay(orderId, obj.getTransactionNo(), order.getOutTradeNo(), attach.getInteger("points"), obj.getProcedureFee());
                                if (count > 0) {
                                    //this.sendPayNotify(orderId);
                                }
                            } else if (payType == WXPAY_VIP) {
                                Long memberId = attach.getLong("memberId");
                                String code = attach.getString("code");
                                count = memberService.buyVipWx(memberId, obj.getOutTradeNo(), code);
                            }
//                            else if (payType == WXPAY_SHIPCARD) {
//                                logger.error("进来购买充值卡逻");
//                                //购买充值卡
//                                Long memberId = attach.getLong("memberId");
//                                Long shipcardId = attach.getLong("shipcardId");
//                                count = memberService.buyShipcardWx(memberId, obj.getOutTradeNo(), shipcardId);
//                            }
                            //电子名片VIP购买回调
                            else if (payType == 188 || payType == 888) {
                                Long memberId = attach.getLong("memberId");
                                String code = attach.getString("code");
                                String level = String.valueOf(payType);
                                count = memberService.buyVipWxCard(memberId, obj.getOutTradeNo(), code, level);
                            } else if (payType == WXPAY_LOCALLIFE_VIP) {
                                Long memberId = attach.getLong("memberId");
                                String code = attach.getString("code");
                                String vipType = attach.getString("vipType");
                                count = memberService.buyLifeVipWx(memberId, obj.getOutTradeNo(), code, Integer.valueOf(vipType));
                            } else if (payType == WXPAY_LOCALLIFE_PREFERENTIAL_CARD) {
                                //不需要处理   前端根据支付完成的状态调用接口实现逻辑
                                Long memberId = attach.getLong("memberId");
                                Member member = new Member();
                                member.setId(memberId);
                                member.setCentreCardFlag(1);
                                memberService.updateMemberAsync(member);
                                count = 1;
                            }
                        } catch (BDException e) {
                            //防止删除不掉 把值设置为false
                            localRedis.setByHours("yfzOrderNotify".concat(obj.getOutTradeNo()), false, 2);
                            //交易未成功删除键
                            localRedis.delByKey("yfzOrderNotify".concat(obj.getOutTradeNo()));
                            e.printStackTrace();
                            logger.error("支付逻辑异常：{}", order, e);
                        }

                        if (count < 1) {
                            logger.error("微信支付回调成功，写入业务逻辑失败，单号：{}", obj.getOutTradeNo());
                            //防止删除不掉 把值设置为false
                            localRedis.setByHours("yfzOrderNotify".concat(obj.getOutTradeNo()), false, 2);
                            //交易未成功删除键
                            localRedis.delByKey("yfzOrderNotify".concat(obj.getOutTradeNo()));
                        }

                        jsonObject.put("returnCode", "0000");
                        jsonObject.put("returnMsg", "");
                        writer.print(jsonObject.toJSONString());
                        writer.close();
                    } else {
                        logger.error("订单已在缓存区!!!!");
                        return;
                    }
                } else {
                    jsonObject.put("returnCode", "-1");
                    jsonObject.put("returnMsg", "inLegal data");
                    writer.print(jsonObject.toJSONString());
                    writer.close();
                }
            }
        } else {
            jsonObject.put("returnCode", "-1");
            jsonObject.put("returnMsg", "inLegal data");
            writer.print(jsonObject.toJSONString());
            writer.close();
        }
    }


    /**
     * 微信支付成功之后的回调通知
     * @param xmlData
     * @return
     * @throws WxPayException
     */
    @PostMapping("/order/notify")
    public String parseOrderNotifyResult(@RequestBody String xmlData) throws WxPayException {
        logger.info("进入微信回调通知");
        final WxPayOrderNotifyResult notifyResult = this.wxPayService.parseOrderNotifyResult(xmlData);

        //验证签名
        notifyResult.checkResult(wxPayService, "JSAPI", false);
        JSONObject attach = JSON.parseObject(notifyResult.getAttach());
        int payType = attach.getIntValue("type");
        if (payType == WXPAY_ORDER) {
            List<Order> orders = orderMapper.selectOrderByOutTradeNo(notifyResult.getOutTradeNo());
            if (orders.isEmpty()) {
                return WxPayNotifyResponse.fail("订单未查到");
            }
        }

        logger.info("订单outTradeNo===========Outer==================" + notifyResult.getOutTradeNo());

        String payId = notifyResult.getTransactionId();
        // JSONObject attach = JSON.parseObject(order.getAttach());
        int result = -1;
        //int payType = attach.getIntValue("type");
        logger.info("订单状态ok==================================" + payType);
        try {
            if (payType == WXPAY_ORDER) {
                Long orderId = attach.getLong("orderId");
                logger.info("逻辑wx修改==================================");
                result = payService.wxPay(orderId, payId, notifyResult.getOutTradeNo(), attach.getInteger("points"), 0L);
                if (result > 0) {
                    //this.sendPayNotify(orderId);
                }
            } else if (payType == WXPAY_VIP) {
                Long memberId = attach.getLong("memberId");
                String code = attach.getString("code");
                result = memberService.buyVipWx(memberId, payId, code);
            }
            //电子名片VIP购买回调
            else if (payType == 188 || payType == 888) {
                Long memberId = attach.getLong("memberId");
                String code = attach.getString("code");
                String level = String.valueOf(payType);
                result = memberService.buyVipWxCard(memberId, payId, code, level);
            } else if (payType == WXPAY_LOCALLIFE_VIP) {
                Long memberId = attach.getLong("memberId");
                String code = attach.getString("code");
                String vipType = attach.getString("vipType");
                result = memberService.buyLifeVipWx(memberId, payId, code, Integer.valueOf(vipType));
            } else if (payType == WXPAY_LOCALLIFE_PREFERENTIAL_CARD) {
                //不需要处理   前端根据支付完成的状态调用接口实现逻辑
                Long memberId = attach.getLong("memberId");
                Member member = new Member();
                member.setId(memberId);
                member.setCentreCardFlag(1);
                memberService.updateMemberAsync(member);
                result = 1;
            }
            if (result < 1) {
                logger.error("微信支付回调成功，写入业务逻辑失败，单号：{}", payId);
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        return WxPayNotifyResponse.success("成功");
    }



    /**
     * 易分账退款回调
     */
    @RequestMapping("/yfz/refundNotify")
    public void yfzRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String publicPath = "";//公钥地址

        String sign = request.getHeader("x-efps-sign");
        BufferedReader br = request.getReader();
        String str = "", wholeStr = "";
        System.out.println("---------------------------------------------------");
        while ((str = br.readLine()) != null) {
            wholeStr += str;
        }
        System.out.println("body:" + wholeStr);
        System.out.println("sign:" + sign);
        System.out.println("---------------------------------------------------");

        PrintWriter writer = response.getWriter();
        JSONObject jsonObject = new JSONObject();
        if (wholeStr != null && !wholeStr.equals("") && sign != null && !sign.equals("")) {
            RefundApplyResponse obj = JSONObject.parseObject(wholeStr, RefundApplyResponse.class);
            JuheOrder juheOrder = orderService.getJuheOrderByOutTradeNo(obj.getOutTradeNo());
            Order order = null;
            Long centreId = null;
            if (juheOrder == null) {
                List<Order> list = orderService.getOrderByOutTradeNo(obj.getOutTradeNo());
                if (ValidateUtil.isNotEmptyCollection(list)) {
                    order = list.get(0);
                    centreId = list.get(0).getCentreId();
                }
            } else {
                centreId = juheOrder.getCenterId();
            }
            if (centreId != null) {
                Centre centre = centreService.getCentreById(centreId);
                boolean result = RsaUtils.vertify(RsaUtils.getPublicKey(Config.getPublicKeyFile(centre.getYplPublicKey())), wholeStr, sign);
                System.out.println("验签结果:" + result);
                if (result) {
                    //退款业务处理
                    payService.yfzRefundDispose(obj.getOutTradeNo(), juheOrder, order);
                    jsonObject.put("returnCode", "0000");
                    jsonObject.put("returnMsg", "");
                    writer.print(jsonObject.toJSONString());
                    writer.close();
                } else {
                    jsonObject.put("returnCode", "-1");
                    jsonObject.put("returnMsg", "inLegal data");
                    writer.print(jsonObject.toJSONString());
                    writer.close();
                }
            } else {
                jsonObject.put("returnCode", "-1");
                jsonObject.put("returnMsg", "inLegal data");
                writer.print(jsonObject.toJSONString());
                writer.close();
            }
        } else {
            jsonObject.put("returnCode", "-1");
            jsonObject.put("returnMsg", "inLegal data");
            writer.print(jsonObject.toJSONString());
            writer.close();
        }
        jsonObject.put("returnCode", "0000");
        jsonObject.put("returnMsg", "");
        writer.print(jsonObject.toJSONString());
        writer.close();
    }

    /**
     * 延迟分账
     */
    @RequestMapping("/yfz/split/call-back")
    public void yfzSplitCallBack(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String sign = request.getHeader("x-efps-sign");
        BufferedReader br = request.getReader();
        String str = "", wholeStr = "";
        System.out.println("---------------------------------------------------");
        while ((str = br.readLine()) != null) {
            wholeStr += str;
        }
        System.out.println("body:" + wholeStr);
        System.out.println("sign:" + sign);
        System.out.println("---------------------------------------------------");

        PrintWriter writer = response.getWriter();
        JSONObject jsonObject = new JSONObject();
        if (wholeStr != null && !wholeStr.equals("") && sign != null && !sign.equals("")) {
            SplitResultQueryResponse obj = JSONObject.parseObject(wholeStr, SplitResultQueryResponse.class);
            String outTradeNo = obj.getOutTradeNo();
            //查看订单是否在缓冲区
            Object orderCash = localRedis.get("yfzOrderSplitNotify".concat(obj.getOutTradeNo()));
            //不在缓冲区进入逻辑
            if (orderCash == null || orderCash.toString().trim().equals("false")) {
                //易票联的回调来得太快了   可能批量新增t_order_split_info表数据的sql都没跑完就进了回调   所以需要先查询判空
                List<OrderSplitInfo> list = orderSplitInfoMapper.selectByOutTradeNo(outTradeNo);
                if (ValidateUtil.isNotEmptyCollection(list)) {
                    //存入缓存 去幂等性
                    localRedis.setByDay("yfzOrderSplitNotify".concat(obj.getOutTradeNo()), true, 1);

                    int count = orderSplitInfoMapper.updateByOutTradeNo(obj.getTransactionNo(), outTradeNo);
                    logger.error("分账支付回调：受影响的行数--" + count + ";outTradeNo--" + outTradeNo + ",transactionNo--" + obj.getTransactionNo());
                    if (obj.getProcedureFee() != null && obj.getProcedureFee() > 0) {
                        orderSplitInfoMapper.updateYfzServiceChargeByOrderIdAndYfzServiceChargeFlag(
                                BigDecimal.valueOf(obj.getProcedureFee()).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_DOWN),
                                outTradeNo, 1);
                    }
                    jsonObject.put("returnCode", "0000");
                    jsonObject.put("returnMsg", "");
                    writer.print(jsonObject.toJSONString());
                    writer.close();
                }
            } else {
                logger.error("订单已在缓存区!!!!");
                return;
            }
        } else {
            jsonObject.put("returnCode", "-1");
            jsonObject.put("returnMsg", "inLegal data");
            writer.print(jsonObject.toJSONString());
            writer.close();
        }
    }


    /**
     * 易分账聚合支付回调
     */
    @RequestMapping("/yfz/notify")
    public void yfzNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        JSONObject attach = null;
        int payType = 0;
        String sign = request.getHeader("x-efps-sign");
        BufferedReader br = request.getReader();
        String str = "", wholeStr = "";
        logger.info("---------------------------------------------------");
        while ((str = br.readLine()) != null) {
            wholeStr += str;
        }
        logger.info("body:" + wholeStr);
        logger.info("sign:" + sign);
        logger.info("---------------------------------------------------");

        PrintWriter writer = response.getWriter();
        JSONObject jsonObject = new JSONObject();
        if (wholeStr != null && !wholeStr.equals("") && sign != null && !sign.equals("")) {

            WxJsOrderNotify obj = JSONObject.parseObject(wholeStr, WxJsOrderNotify.class);
            JuheOrder juheOrder = orderService.getJuheOrderByOutTradeNo(obj.getOutTradeNo());
            if (juheOrder != null) {
                Centre centre = centreService.getCentreById(juheOrder.getCenterId());
                boolean result = RsaUtils.vertify(RsaUtils.getPublicKey(Config.getPublicKeyFile(centre.getYplPublicKey())), wholeStr, sign);
                System.out.println("验签结果:" + result);
                if (result) {
                    //查看订单是否在缓冲区
                    Object orderCash = localRedis.get("yfzJuHeNotify".concat(obj.getOutTradeNo()));
                    //不在缓冲区进入逻辑
                    if (orderCash == null || orderCash.toString().trim().equals("false")) {
                        //存入缓存 去幂等性
                        localRedis.setByDay("yfzJuHeNotify".concat(obj.getOutTradeNo()), true, 1);
                        int result1 = -1;
                        //门店费率操作
                        //collectionFlowService.juheOrderByCollectionFlowInsert(juheOrder);

                        result1 = payService.juhePay(juheOrder.getId(), juheOrder.getOutTradeNo(), juheOrder.getOutTradeNo(), obj.getProcedureFee());
                        if (result1 > 0) {
                            //this.sendPayNotify(orderId);
                        }
                        if (result1 < 1) {
                            logger.info("======================易票联回调成功业务逻辑处理失败===========================");
                            //防止删除不掉 把值设置为false
                            localRedis.setByDay("yfzJuHeNotify".concat(obj.getOutTradeNo()), false, 1);
                            //交易未成功删除键
                            localRedis.delByKey("yfzJuHeNotify".concat(obj.getOutTradeNo()));
                        }
                        logger.info("=========易票联回调返回");

                        jsonObject.put("returnCode", "0000");
                        jsonObject.put("returnMsg", "");
                        writer.print(jsonObject.toJSONString());
                        writer.close();
                    } else {
                        logger.error("订单已在缓存区!!!!");
                        return;
                    }
                } else {
                    jsonObject.put("returnCode", "-1");
                    jsonObject.put("returnMsg", "inLegal data");
                    writer.print(jsonObject.toJSONString());
                    writer.close();
                }
            } else {
                jsonObject.put("returnCode", "-1");
                jsonObject.put("returnMsg", "inLegal data");
                writer.print(jsonObject.toJSONString());
                writer.close();
            }
        } else {
            jsonObject.put("returnCode", "-1");
            jsonObject.put("returnMsg", "inLegal data");
            writer.print(jsonObject.toJSONString());
            writer.close();
        }

    }





}
